# EquipmentManagement/views.py
# Create your views here.

from DataStatistics.models import defectDataMain
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet

# import pandas as pd
from django.shortcuts import render, HttpResponse
from django.http import JsonResponse
import json
from django.db.models import Q
from django.db.models import Count
from django.db import connection
import shutil
import os
from pathlib import Path
from django.http import HttpResponseBadRequest
import re
from conf.const import *
from asgiref.sync import sync_to_async
import ast
import astunparse
# -----------------------------------
class defectDataSerializer(CustomModelSerializer):
    class Meta:
        model = defectDataMain
        fields = "__all__"
        read_only_fields = ["id"]

class defectDataCreateUpdateSerializer(CustomModelSerializer):
    class Meta:
        model = defectDataMain
        fields = '__all__'

class defectDataViewSet(CustomModelViewSet):
    queryset = defectDataMain.objects.all()
    # print(CustomModelViewSet)
    serializer_class = defectDataSerializer
    extra_filter_backends = []
    permission_classes = []
    search_fields = ['label']

# -------------------------------------------------
def import_data(request):
    if request.method == 'GET':
        response = HttpResponse('connect_success')
        return response

    if request.method == 'POST':
        data = json.loads(request.body)
        # print(data)
        
        id = data.get('id')
        defectid = data.get('defectid')
        productid = data.get('productid')
        productname = data.get('productname')
        cameraid = data.get('cameraid')
        cameraname = data.get('cameraname')
        batchnum = data.get('batchnum')
        reelnum = data.get('reelnum')
        hlength = data.get('hlength')
        vlength = data.get('vlength')
        area = data.get('area')
        speed = data.get('speed')
        machinecode = data.get('machinecode')
        defecparamname = data.get('defecparamname')
        defecparamid = data.get('defecparamid')
        defecparamtype = data.get('defecparamtype')
        defecparamconfidene = data.get('defecparamconfidene')
        defecparamshape = data.get('defecparamshape')
        date = data.get('date')
        imagename = data.get('imagename').replace(".bmp", ".jpg")
        imgDate = re.search(r"\d{4}-\d{2}-\d{2}", imagename)
        imagepath = BASE_FILE_PATH + str(imgDate.group()) + '/'
        xaxis = data.get('xaxis')
        yaxis = data.get('yaxis')
        xpixel = data.get('xpixel')
        ypixel = data.get('ypixel')
        wpixel = data.get('wpixel')
        hpixel = data.get('hpixel')
        ignore = data.get('ignore')
        eliminate = data.get('eliminate')
        
        model = defectDataMain(id = id,defectid = defectid,productid = productid
                           ,productname = productname,cameraid = cameraid,cameraname = cameraname
                           ,batchnum = batchnum,reelnum = reelnum,hlength = hlength,vlength = vlength
                           ,area = area,speed = speed,machinecode = machinecode
                           ,defecparamname = defecparamname,defecparamid = defecparamid,defecparamtype = defecparamtype
                           ,defecparamconfidene = defecparamconfidene,defecparamshape = defecparamshape,date = date
                           ,imagepath = imagepath,imagename = imagename,xaxis = xaxis,yaxis = yaxis,xpixel = xpixel
                           ,ypixel = ypixel,wpixel = wpixel,hpixel = hpixel,ignore = ignore,eliminate = eliminate)
        model.save()
        # {'id': '', 'defectid': 'DT1687003604821', 'productid': 'C5 - 深黑 - 
        # 155 - 2', 'productname': '', 'cameraid': 'S2164984', 'cameraname': '', 'batchnum': '7220923184',
        #  'reelnum': '1', 'hlength': '6.50', 'vlength': '5.76', 'area': '37.44', 'speed': '0', 
        # 'machinecode': '', 'defecparamname': '大烂胶', 'defecparamid': 'brokenglue', 
        # 'defecparamtype': 'brokenglue', 'defecparamconfidene': '0.694904', 'defecparamshape': '',
        #  'date': '1687003604821', 'imagepath': 'D:\\image\\Label\\2023-06-17', 
        # 'imagename': '2023-06-17 20-06-44-780-0.bmp', 'xaxis': '295.30', 'yaxis': '598.32',
        #  'xpixel': '2953', 'ypixel': '6648', 'wpixel': '65', 
        # 'hpixel': '64', 'ignore': '0', 'eliminate': '0'}
        # std_data = {
        #     "code": 2000,
        #     "data": {
        #         "page": 1,
        #         "limit": 1,
        #         "total": 1,
        #         "data": 1
        #     },
        #     "msg": "1"
        # }
        response = HttpResponse('success')
        return response
    
    return HttpResponse('fail')

def defectDataFilter(request):
    if request.method == 'GET':
        startTime_get = request.GET.get('startTime')
        endTime_get = request.GET.get('endTime')
        batchnum_get = request.GET.get('batchnum')
        reelnum_get = request.GET.get('reelnum')
        machinecode_get = request.GET.get('machinecode')
        # 1和0 1为全选 0为非全选
        isAll = request.GET.get('isAll')
        defectType = request.GET.get('defectType')
        if defectType != None:
            defectType_get = defectType.split(',')
            print(defectType_get)
        page = int(request.GET.get('page'))
        limit = int(request.GET.get('limit'))
        filters = Q()
        if(machinecode_get != None and len(machinecode_get) != 0):
            filters = filters & Q(machinecode = machinecode_get)
        if(batchnum_get != None and len(batchnum_get) != 0):
            filters = filters & Q(batchnum = batchnum_get)
        if(reelnum_get != None and len(reelnum_get) != 0):
            filters = filters & Q(reelnum = reelnum_get)
        if(startTime_get != None and len(startTime_get) != 0):
            filters = filters & Q(date__gt = startTime_get)
        if(endTime_get != None and len(endTime_get) != 0):
            filters = filters & Q(date__lt = endTime_get)
        if(isAll=="0" and defectType != None and len(defectType) != 0):
            filters = filters & Q(defecparamtype__in=defectType_get)
        queryset = defectDataMain.objects.filter(filters).order_by('dataId')[((page-1)*limit):((page-1)*limit) + limit]
        countSet = defectDataMain.objects.filter(filters).count()
        defectCategory = defectDataMain.objects.filter(filters).values('defecparamname').annotate(count=Count('defecparamname')).order_by()
        cList = []
        for entry in defectCategory:
            cList.append(entry)
        data = defectDataSerializer(queryset, many=True).data
        std_data = {
            "code": 2000,
            "data": {
                "page": page,
                "limit": limit,
                "total": countSet,
                "data": data,
                "category": cList
            },
            "msg": "1"
        }
    # queryset = MPNPlace.objects.raw("SELECT  COUNT(DISTINCT  PLACELAYER)  from  dvadmin_mpnplace ;")
        return JsonResponse(std_data)
    return HttpResponse('fail')

def defectDataBatchFilter(request):
    if request.method == 'GET':
        batchnum_get = request.GET.get('batchnum')
        page = int(request.GET.get('page'))
        limit = int(request.GET.get('limit'))
        data = []
        cList = []
        distinct_categories = defectDataMain.objects.values('reelnum').annotate(count=Count('reelnum')).order_by('count')
        for entry in distinct_categories:
            category = entry['reelnum']
            count = entry['count']
            filters = Q()
            filters = filters & Q(batchnum = batchnum_get)
            filters = filters & Q(reelnum = category)
            queryset = defectDataMain.objects.filter(filters).order_by('dataId')[((page-1)*limit):((page-1)*limit) + limit]
            countSet = defectDataMain.objects.filter(filters).count()
            data.append(defectDataSerializer(queryset, many=True).data) 
            cList.append({
                "c": category,
                "s": count
            })
            
        std_data = {
            "code": 2000,
            "data": {
                "page": page,
                "limit": limit,
                "total": countSet,
                "data": data,
                "categoryList": cList
            },
            "msg": "1"
        }
    # queryset = MPNPlace.objects.raw("SELECT  COUNT(DISTINCT  PLACELAYER)  from  dvadmin_mpnplace ;")
        return JsonResponse(std_data)
    return HttpResponse('fail')

def defectMapFilter(request):
    if request.method == 'GET':
        batchnum_get = request.GET.get('batchnum')
        reelnum_get = request.GET.get('reelnum')
        startTime_get = request.GET.get('startTime')
        endTime_get = request.GET.get('endTime')
        machinecode_get = request.GET.get('machinecode')
        # 1和0 1为全选 0为非全选
        isAll = request.GET.get('isAll')
        defectType = request.GET.get('defectType')
        if defectType != None:
            defectType_get = defectType.split(',')
        filters = Q()
        if(machinecode_get != None and len(machinecode_get) != 0):
            filters = filters & Q(machinecode = machinecode_get)
        if(batchnum_get != None and len(batchnum_get) != 0):
            filters = filters & Q(batchnum = batchnum_get)
        if(reelnum_get != None and len(reelnum_get) != 0):
            filters = filters & Q(reelnum = reelnum_get)
        if(startTime_get != None and len(startTime_get) != 0):
            filters = filters & Q(date__gt = startTime_get)
        if(endTime_get != None and len(endTime_get) != 0):
            filters = filters & Q(date__lt = endTime_get)
        if(isAll=="0" and defectType != None and len(defectType) != 0):
            filters = filters & Q(defecparamtype__in=defectType_get)
        queryset = defectDataMain.objects.filter(filters).order_by('dataId')
        countSet = defectDataMain.objects.filter(filters).count()
        data = defectDataSerializer(queryset, many=True).data
        std_data = {
            "code": 2000,
            "data": {
                "total": countSet,
                "data": data,
            },
            "msg": "1"
        }
    # queryset = MPNPlace.objects.raw("SELECT  COUNT(DISTINCT  PLACELAYER)  from  dvadmin_mpnplace ;")
        return JsonResponse(std_data)
    return HttpResponse('fail')

def defectBatchAndReel(request):
    if request.method == 'GET':
        
        # 使用 annotate 方法对字段进行聚合，并使用 Count 统计不同值的数量
        queryset = defectDataMain.objects.values('batchnum').annotate(value_count=Count('batchnum'))

        # 获取不同值的数量
        distinct_value_count = queryset.count()

        # 获取不同值及其数量的列表
        distinct_values_with_count = queryset.values_list('batchnum', 'value_count')

        std_data = {
            "code": 2000,
            "data": {
            },
            "msg": "1"
        }
    # queryset = MPNPlace.objects.raw("SELECT  COUNT(DISTINCT  PLACELAYER)  from  dvadmin_mpnplace ;")
        return JsonResponse(std_data)
    return HttpResponse('fail')


# 收图片
def defectImage(request):
    if request.method == 'POST':
        photoName = request.headers['Image-Name'].replace(".bmp", ".jpg")
        # first_space_index = photoName.index(" ")
        # photoDate = photoName[:first_space_index]
        photoDate = re.search(r"\d{4}-\d{2}-\d{2}", photoName)
        # 指定目录路径
        directory = BASE_FILE_PATH + str(photoDate.group()) + '/'
        # 检查目录是否存在
        if not os.path.exists(directory):
            # 创建目录
            os.makedirs(directory)
        with open(directory + photoName, 'wb') as f: f.write(request.body) 
        response = HttpResponse('success')
        return response
    if request.method == 'GET':
        response = HttpResponse('connect_success')
        return response
    return HttpResponseBadRequest('fail')

# 读图片路径
def readDefectImage(request):
    if request.method == 'GET':
        # 指定文件夹路径
        folder_path = Path('/Users/hukaihang/Downloads/photo/')

        # 获取文件夹中的所有文件和子文件夹的Path对象
        contents = folder_path.iterdir()
        
        # 遍历文件夹内容
        # 遍历文件夹内容并判断类型
        for item in contents:
            if item.is_file():
                print(f'{item.name} 是文件')
            elif item.is_dir():
                print(f'{item.name} 是文件夹')
            else:
                print(f'{item.name} 是其他类型')
        std_data = {
            "code": 2000,
            "data": {
            },
            "msg": "1"
        }
        return JsonResponse(std_data)
    
    return HttpResponse('fail')

# 最近瑕疵检测
def defectLatest(request):
    cursor = connection.cursor()
    if request.method == 'GET':
        startTime_get = request.GET.get('startTime')
        endTime_get = request.GET.get('endTime')
        cursor.execute('SELECT machinecode, batchnum, reelnum FROM dvadmin_defect_data_main WHERE date >= %s AND date <= %s GROUP BY machinecode, batchnum, reelnum;',(startTime_get,endTime_get))
        raw = cursor.fetchall()
        countSet = len(raw)
        std_data = {
            "code": 2000,
            "data": {
                "total": countSet,
                "data": raw,
            },
            "msg": "1"
        }
        return JsonResponse(std_data)
    return HttpResponse('fail')

# 所有订单号和卷号查询
def defectallBatchReel(request):
    cursor = connection.cursor()
    if request.method == 'GET':
        cursor.execute('SELECT DISTINCT batchnum, reelnum FROM dvadmin_defect_data_main WHERE batchnum IS NOT NULL AND reelnum IS NOT NULL;')
        raw = cursor.fetchall()
        countSet = len(raw)
        # 将二维数组转换成key-value，例如转换成key-value，”1“：[1,2,3],"2":[1]
        result = {}
        for pair in raw:
            key = str(pair[0])
            value = pair[1]
            if key in result:
                result[key].append(value)
            else:
                result[key] = [value]
        std_data = {
            "code": 2000,
            "data": {
                "total": countSet,
                "data": result,
            },
            "msg": "1"
        }
        return JsonResponse(std_data)
    return HttpResponse('fail')

# 读取文件夹信息
def defectReadDir(request):
    if request.method == 'GET':
        # 返回文件夹名称数组
        dirs = []
        msg= ""
        # 指定文件夹路径
        try:
            folder_path = Path(BASE_FILE_PATH)
            # 获取文件夹中的所有文件和子文件夹的Path对象
            contents = folder_path.iterdir()
            # 遍历文件夹内容
            # 遍历文件夹内容并判断类型
            for item in contents:
                if item.is_dir():
                    dirs.append(item.name)
            msg = "ok"
        except:
            msg= "fail"
        std_data = {
            "code": 2000,
            "data": {
                "data": dirs,
                "msg": msg
            },
            "msg": "1"
        }
        return JsonResponse(std_data)
    
    return HttpResponse('fail')

# 删文件夹
async def defectDelDir(request):
    if request.method == 'GET':
        dirName = request.GET.get('dirName')
        directory = BASE_FILE_PATH + dirName
        # 检查目录是否存在
        if not os.path.exists(directory):
            return HttpResponse('fail')
        # 异步执行删除操作
        sql = 'DELETE FROM dvadmin_defect_data_main WHERE Date(create_datetime) = %s;'
        await sync_to_async(connection.cursor().execute)(sql, (dirName,))
        shutil.rmtree(directory)
    return HttpResponse('success')

# 获取指定文件夹中图片路径，并且分页获取，参数1:文件夹名称，参数2:每页数目，参数3：第几页
def defectGetImageByDirName(request):
    if request.method == 'GET':
        dirName = request.GET.get('dirName')
        size = int(request.GET.get('size'))
        current = int(request.GET.get('current'))
        start_index = (current - 1) * size
        end_index = start_index + size 
        image_files = []
        image_count = 0
        folder_path = BASE_FILE_PATH + dirName
        for filename in os.listdir(folder_path):
            if image_count >= end_index:
                break

            file_path = os.path.join(folder_path, filename)
            if image_count >= start_index and os.path.isfile(file_path):
                image_files.append(file_path)
            image_count += 1
        std_data = {
            "code": 2000,
            "data": {
                "data": image_files
            },
            "msg": "1"
        }
        return JsonResponse(std_data)
    return HttpResponse('fail')

# 根据图片路径传图片
def defectGetImageByName(request):
    if request.method == 'GET':
        imgPath = request.GET.get('imgPath')
        # 检查图片是否存在
    if os.path.exists(imgPath):
        # 打开图片文件
        with open(imgPath, 'rb') as f:
            response = HttpResponse(content_type='multipart/x-mixed-replace; boundary=frame')
            response.write(b'--frame\r\n')
            response.write(b'Content-Type: image/jpeg\r\n\r\n')
            response.write(f.read())
            response.write(b'\r\n')
        return response    
    else:
        # 图片不存在，返回 404 响应
        return HttpResponse('fail')

# 更改清除文件周期(天)
def defectClearFile(request):
    if request.method == 'GET':
        day = request.GET.get('day')
        
        # 修改常量值
        # 打开 Python 文件
        with open(CONST_FILE_PATH, "r") as file:
            # 读取文件内容
            file_content = file.read()

            # 在文件内容中查找变量并修改其值
            # 假设变量名为 target_variable
            import re
            match = re.search(r"(SAVE_PHOTO_DAY\s*=\s*)(.*)", file_content)
            if match:
                # 获取变量行的前缀和后缀
                prefix = match.group(1)
                suffix = match.group(2)

                # 修改变量的新值
                new_value = day

                # 构造新的文件内容
                new_file_content = file_content.replace(match.group(), prefix + new_value)

        # 将修改后的内容写回文件
        with open(CONST_FILE_PATH, "w") as file:
            file.write(new_file_content)
            std_data = {
            "code": 2000,
            "msg": "success"
        }
        return JsonResponse(std_data)
    return HttpResponse('fail')

# 根据订单号查询相关卷号机器号
def defectByBatchnum(request):
    cursor = connection.cursor()
    if request.method == "GET":
        batchnum = request.GET.get('batchnum')
        cursor.execute('SELECT DISTINCT reelnum,machinecode FROM dvadmin_defect_data_main where batchnum = %s;',(batchnum,))
        raw = cursor.fetchall()
        # 将二维数组转换成key-value，例如转换成key-value，”1“：[1,2,3],"2":[1]
        result = {}
        for pair in raw:
            key = str(pair[0])
            value = pair[1]
            if key in result:
                result[key].append(value)
            else:
                result[key] = [value]
        std_data = {
            "code": 2000,
            "data": result,
            "msg": "success"
        }
        return JsonResponse(std_data)
    return HttpResponse('fail')

# 获取自动删除天数
def defectGetDelDay(request):
    if request.method == "GET":
         # 打开 Python 文件
        with open(CONST_FILE_PATH, "r") as file:
            # 读取文件内容
            file_content = file.read()

            # 在文件内容中查找变量
            # 假设变量名为 SAVE_PHOTO_DAY
            SAVE_PHOTO_DAY = None

            # 使用正则表达式或其他方法从文件内容中提取目标变量的值
            import re
            match = re.search(r"SAVE_PHOTO_DAY\s*=\s*(.*)", file_content)
            if match:
                target_variable = match.group(1)

        # 保存最近x天照片
        interval_time = int(target_variable)
       
        std_data = {
            "code": 2000,
            "data": interval_time,
            "msg": "success"
        }
        return JsonResponse(std_data)
    return HttpResponse('fail')

# 设置自动删除天数
def defectSetDelDay(request):
    if request.method == "GET":
        delDay = request.GET.get('delDay')
        # 读取 Python 文件
        with open(CONST_FILE_PATH, "r") as file:
            source_code = file.read()

        # 解析 Python 代码
        tree = ast.parse(source_code)

        # 查找并修改变量
        target_variable = "SAVE_PHOTO_DAY"
        new_value = delDay

        for node in ast.walk(tree):
            if isinstance(node, ast.Assign) and isinstance(node.targets[0], ast.Name) and node.targets[0].id == target_variable:
                node.value = ast.parse(new_value).body[0].value

        # 生成修改后的代码
        modified_code = astunparse.unparse(tree)
        
        # 将修改后的代码保存回文件
        with open(CONST_FILE_PATH, "w") as file:
            file.write(modified_code)

        std_data = {
            "code": 2000,
            "msg": "success"
        }
        return JsonResponse(std_data)
    return HttpResponse('fail')

# 根据时间范围查询单号
def defectTimeFilter(request):
    if request.method == 'GET':
        startTime_get = request.GET.get('startTime')
        endTime_get = request.GET.get('endTime')
        filters = Q()
        if(startTime_get != None and len(startTime_get) != 0):
            filters = filters & Q(date__gt = startTime_get)
        if(endTime_get != None and len(endTime_get) != 0):
            filters = filters & Q(date__lt = endTime_get)
        queryset = defectDataMain.objects.filter(filters).values('batchnum').annotate(count=Count('batchnum')).order_by('batchnum')
        print(queryset)
        data =  [item["batchnum"] for item in list(queryset)]
        std_data = {
            "code": 2000,
            "data": {
                "data": data,
            },
            "msg": "查询成功"
        }
    # queryset = MPNPlace.objects.raw("SELECT  COUNT(DISTINCT  PLACELAYER)  from  dvadmin_mpnplace ;")
        return JsonResponse(std_data)
    return HttpResponse('fail')